//
//  ZZ.swift
//  AliIndexEffect
//
//  Created by 陈钟 on 2019/12/9.
//  Copyright © 2019 陈钟. All rights reserved.
//

import UIKit

public extension UIScrollView {

    private var topViewOldValue: UIView?{
        set{
            let key: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "topViewOldValue".hashValue)
            objc_setAssociatedObject(self, key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        get{
            let key: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "topViewOldValue".hashValue)
            let obj = objc_getAssociatedObject(self, key)
            return obj as? UIView
        }
    }
    /// 设置顶部显示的窗体 将在设置zz_headerViewHeight后自动调整高度 宽度将自动调整
    var zz_topView: UIView?{
        set{
            self.topViewOldValue?.removeFromSuperview()
            if newValue == nil {
                self.removeObserver()
            }else{
                self.addObserver()
            }
            self.topViewOldValue = newValue
        }
        get{
            return self.topViewOldValue
        }
    }

    /// 顶部窗体的显示高度
    var zz_topViewHeight: CGFloat{
        set{
            let key: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "zz_topViewHeight".hashValue)
            objc_setAssociatedObject(self, key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

            self.contentInset = UIEdgeInsets(top: newValue, left: 0, bottom: 0, right: 0)
            self.scrollIndicatorInsets = UIEdgeInsets(top: newValue, left: 0, bottom: 0, right: 0)
            self.contentOffset = CGPoint(x: 0, y: -newValue)

            self.refreshFrame()
        }
        get{
            let key: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "zz_topViewHeight".hashValue)
            let obj = objc_getAssociatedObject(self, key)
            return (obj as? CGFloat) ?? 0
        }
    }


    /// 窗体拖出显示区域后 固定显示高度（高度由窗体底部向上计算）
    var zz_topViewShowHeight: CGFloat{
        set{
            let key: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "zz_topViewShowHeight".hashValue)
            objc_setAssociatedObject(self, key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

            self.refreshFrame()
        }
        get{
            let key: UnsafeRawPointer! = UnsafeRawPointer.init(bitPattern: "zz_topViewShowHeight".hashValue)
            let obj = objc_getAssociatedObject(self, key)
            return (obj as? CGFloat) ?? 0
        }
    }

    /// 监听UIScrollView的大小变更 和 contentOffset变更
    private func addObserver(){
        self.addObserver(self, forKeyPath: "frame", options: [.new,.old], context: nil)
        self.addObserver(self, forKeyPath: "bounds", options: [.new,.old], context: nil)
        self.addObserver(self, forKeyPath: "contentOffset", options: [.new,.old], context: nil)
    }
    private func removeObserver(){
        self.removeObserver(self, forKeyPath: "frame")
        self.removeObserver(self, forKeyPath: "bounds")
        self.removeObserver(self, forKeyPath: "contentOffset")
    }

    /// 刷新zz_headerView frame
    private func refreshFrame(){
        guard let headerView = self.zz_topView else { return }
        self.addSubview(headerView)

        var h_Frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.zz_topViewHeight)

        let offsetY = self.contentOffset.y
        if offsetY <= -self.zz_topViewHeight {
            h_Frame.origin.y = offsetY
        }else if (offsetY >= -self.zz_topViewShowHeight){
//            if offsetY > 0 {
//                self.contentInset = UIEdgeInsets(top: self.zz_headerViewShowHeight, left: 0, bottom: 0, right: 0)
//            }else{
//                self.contentInset = UIEdgeInsets(top: self.zz_headerViewHeight, left: 0, bottom: 0, right: 0)
//            }
            h_Frame.origin.y = offsetY - (self.zz_topViewHeight - self.zz_topViewShowHeight)
        }else{
            h_Frame.origin.y = -self.zz_topViewHeight
        }

        headerView.frame = h_Frame
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        switch keyPath {
            case "frame","bounds","contentOffset":
                self.refreshFrame()
                break
            default: break
        }
    }

}
